home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / arcers / tar316.zip / STREAMER.C < prev    next >
Text File  |  1980-07-24  |  20KB  |  710 lines

  1. #ifdef __TURBOC__
  2. #include <dos.h>
  3. #include <errno.h>
  4. #include <string.h>
  5.  
  6. #include "qic02.h"
  7.  
  8. /*****************************************************\
  9.  * Quarter-Inch-Cartridge no. 02 standart error list *
  10. \*****************************************************/
  11.  
  12. static char *err[] = {
  13.    "udefined error",
  14.    "Ok",
  15.    "reset in progress",    /* hardware status */
  16.    "end of recorded media",
  17.    "bus parity error",
  18.    "beginning of media",
  19.    "marginal block detected",
  20.    "no data detected",
  21.    "illegal command",
  22.    "timeout expired",    /* software flag */
  23.    "file mark detected",
  24.    "block not located",
  25.    "unrecoverable data error",
  26.    "end of medium",
  27.    "write protected",
  28.    "device fault",
  29.    "cartridge not in place",
  30.    "drive busy",    /* software error codes */
  31.    "device not opened",
  32.    "device already opened",
  33. };
  34.  
  35. char **qic02_errlist = err+1;
  36. int  qic02_nerr = sizeof(err)/sizeof(*err) - 1;
  37.  
  38. /****************************************************\
  39.  * Quarter-Inch-Cartridge no. 02 standart interface *
  40. \****************************************************/
  41.  
  42. extern unsigned long timer(void);
  43. extern unsigned long suspend_value(unsigned);
  44. extern void suspend(unsigned long);
  45. extern void interrupt cthandle();
  46. extern long ptr2abs(void far *);
  47.  
  48. static unsigned long wait03us, wait25ms;
  49.  
  50. #define CT_OPENED  0x08
  51. #define CT_CHECKED 0x10
  52. #define CT_EVENT   0x20
  53. #define CT_PROTECT 0x40
  54.  
  55. #define MASK_BOARD 0x7f
  56. #define SKIP_RESET 0x80
  57.  
  58. /* Calculate number of ticks by 300 ms units */
  59. #define TIMEOUT(x) (int)((3*119318L*(x) + 65535L) / 65536L)
  60. #define MINTIME    TIMEOUT(1)
  61. #define MAXTIME    TIMEOUT(1000)
  62. #define WAITIME    TIMEOUT(10)
  63. #define HALT_CPU   /*__emit__(0xf4)*/
  64. #define dim(x)     (sizeof(x)/sizeof(*(x)))
  65. #define NTRY       3
  66.  
  67. #define Q2_READBIT 0x80
  68. #define DMA_WRDEV  8
  69. #define DMA_RDDEV  4
  70.  
  71. #define ALIASLEN 8
  72.  
  73. struct _ct_define {
  74.    char (*aliases)[ALIASLEN]; int naliases;
  75.    WORD valid_base, off_control, off_data, off_launch, off_clear;
  76.    BYTE mask_reset, val_reset;
  77.    BYTE mask_event, not_event;
  78.    BYTE mask_ready, not_ready;
  79.    BYTE mask_excep, not_excep;
  80.    BYTE mask_dma,   done_dma;
  81.    BYTE mask_xfer,  no_xfer;
  82.  
  83.    BYTE set_reset, set_request, set_online;
  84.    BYTE ienable, denable, dma_valid, rundma[8];
  85. };
  86.  
  87. static char archivenames[][ALIASLEN]={
  88.    "archive","fastape", "sc499", "sc-499", "sc402", "sc-402",
  89. };
  90. static char everexnames [][ALIASLEN]={
  91.    "everex", "sc409a", "sc-409a",
  92. };
  93. static char wangteknames[][ALIASLEN]={
  94.    "wangtek",
  95. };
  96.  
  97.  
  98. struct _ct_define sc499 = {
  99.    archivenames, dim(archivenames),
  100.    0x3f8, 1, 0, 2, 3,
  101.    0xf0, 0x50,
  102.    0x80, 0x80,
  103.    0x40, 0x40,
  104.    0x20, 0x20,
  105.    0x10, 0x10,
  106.    0x08, 0x00,
  107.  
  108.    0x80, 0x40, 0,
  109.    0x20, 0x10, 0x0A, { 0, 0, 0, 0, 0, 0, 0, 0 },
  110. };
  111.  
  112. struct _ct_define sc409a = {
  113.    everexnames, dim(everexnames),
  114.    0x3ff, 0, 1, UNUSED, UNUSED,
  115.    7,    5,
  116.    0,    0,
  117.    1,    1,
  118.    2,    2,
  119.    0,    0,
  120.    4,    4,
  121.  
  122.    2, 4, 1,
  123.    0x40, 0, 0x0E, { 0, 8, 8, 8, 0, 0, 0, 0 },
  124. };
  125.  
  126. struct _ct_define wangtek = {
  127.    wangteknames, dim(wangteknames),
  128.    0x3ff, 0, 1, UNUSED, UNUSED,
  129.    7,    5,
  130.    0,    0,
  131.    1,    1,
  132.    2,    2,
  133.    0,    0,
  134.    4,    4,
  135.  
  136.    2, 4, 1,
  137.    0, 0, 0x0E, { 0, 8, 8, 16, 0, 0, 0, 0 },
  138. };
  139.  
  140. struct _ct_define *ct_list[] = {
  141.    &sc499, &sc409a, &wangtek
  142. };
  143.  
  144. struct _ct_pic {
  145.    WORD base;
  146.    BYTE ack, chain;
  147.    void interrupt (*old)();
  148.    int number; BYTE save;
  149. } ct_pic;
  150.  
  151. struct _ct_dma {
  152.    WORD page, address, counter;
  153.    WORD mask, mode, clear;
  154.    BYTE read, write;
  155. } ct_dma;
  156.  
  157. BYTE lastcmd = UNUSED;
  158. WORD ct_error;
  159. volatile struct _ct_psw {
  160.    BYTE flags;
  161.    BYTE input;
  162. } ct_psw;
  163.  
  164. struct _ct_control {
  165.    WORD control, data, launch, clear;
  166.    BYTE mask_reset, val_reset;
  167.    BYTE mask_event, not_event;
  168.    BYTE mask_ready, not_ready;
  169.    BYTE mask_excep, not_excep;
  170.    BYTE mask_state, inv_state;
  171.    BYTE mask_xfer,  no_xfer;
  172.    BYTE mask_dma,   done_dma;
  173.  
  174.    BYTE do_reset, request, online;
  175.    BYTE int_enable, done_enable, dma_enable;
  176. } ct_set;
  177.  
  178. static WORD ct_error;
  179. static BYTE statbuf[6];
  180.  
  181. #define ctlport    (ct_set.control)
  182. #define cmdport    (ct_set.data)
  183. #define statport   (ct_set.control)
  184. #define dataport   (ct_set.data)
  185.  
  186. #define DMAGO      (ct_set.launch)
  187. #define DMACL      (ct_set.clear)
  188.  
  189. #define MASK_RESET ct_set.mask_reset
  190. #define VAL_RESET  ct_set.val_reset
  191. #define MASK_READY ct_set.mask_ready
  192. #define NOT_READY  ct_set.not_ready
  193. #define MASK_EXCEP ct_set.mask_excep
  194. #define NOT_EXCEP  ct_set.not_excep
  195. #define MASK_STATE ct_set.mask_state
  196. #define INV_STATE  ct_set.inv_state
  197. #define DIRC       ct_set.mask_xfer
  198. #define XOFF       ct_set.no_xfer
  199. #define ON         ct_set.online
  200. #define REQ        ct_set.request
  201. #define RESET      ct_set.do_reset
  202. #define EI         ct_set.int_enable
  203. #define ED         ct_set.done_enable
  204. #define DMA        ct_set.dma_enable
  205. #define INP        ct_psw.input
  206. #define DMA_MAIN   ct_dma.mask
  207.  
  208. #define WAIT_READY(t)\
  209.     for ((t)=timer(); ((INP=inportb(statport))&MASK_READY)==NOT_READY;)\
  210.         { if (timer()-(t) > MINTIME) goto error; }
  211. #define WAIT_BUSY(t)\
  212.     for ((t)=timer(); ((INP=inportb(statport))&MASK_READY)!=NOT_READY;)\
  213.         { if (timer()-(t) > MINTIME) goto error; }
  214.  
  215. static int ct_iobyte(int c, unsigned char *p, unsigned length, unsigned tout)
  216. {
  217.    register i;
  218.    register long t, t0;
  219. #if 0
  220.    /* read-only now */ if (!(c & Q2_READBIT)) goto error;
  221. #endif
  222.    ct_psw.flags &= ~CT_CHECKED;
  223.    outportb(cmdport, lastcmd=c);
  224.    outportb(ctlport, REQ);
  225.    WAIT_READY(t);
  226.    outportb(ctlport, ON); /* Clear request */
  227.    WAIT_BUSY(t);
  228.  
  229.    t0 = timer();
  230.    i = c & Q2_READBIT ? XOFF : XOFF^DIRC;
  231.    while (((INP=inportb(statport)) & DIRC)==XOFF) {
  232.       if (timer()-t0 > tout) goto error;
  233.    }
  234.    for (i=0; i<length; i++) {
  235.       WAIT_READY(t);
  236.       if (c & Q2_READBIT) {
  237.          p[i] = inportb(dataport);
  238.       } else {
  239.          outportb(dataport, p[i]);
  240.       }
  241.       outportb(ctlport, REQ);
  242.       suspend(wait03us);
  243.       WAIT_BUSY(t);
  244.       outportb(ctlport, ON);
  245.    }
  246.    return i;
  247. error:
  248.    ct_error = Q2E_DEAD;
  249.    ct_psw.flags |= CT_CHECKED;
  250.    errno = EFAULT;
  251.    return -1;
  252. }
  253.  
  254. static int ct_test(void)
  255. {
  256.    register n;
  257.    register long t;
  258.  
  259.    for (t=timer(); ((INP=inportb(statport))&MASK_STATE)==INV_STATE;) {
  260.       if (timer()-t > MINTIME) {
  261.          ct_error = Q2E_BUSY; goto end;
  262.       }
  263.       HALT_CPU;
  264.    }
  265.    for (n=NTRY; n; n--) {
  266.       if (ct_iobyte(Q2_RDSTAT, statbuf, 6, TIMEOUT(10)) == 6) {
  267.          ct_error = (statbuf[0] & Q2_ERRFLAG) ?
  268.             (statbuf[0] & Q2_ERRMASK) << 8 : 0;
  269.          if (statbuf[1] & Q2_ERRFLAG) ct_error |= statbuf[1] & Q2_ERRMASK;
  270.          break;
  271.       }
  272.    }
  273. end:
  274.    ct_psw.flags |= CT_CHECKED;
  275.    return ct_error;
  276. }
  277.  
  278. static int ct_wait(BYTE mask, BYTE val, unsigned long t0, unsigned tout)
  279. {
  280.    while (((INP=inportb(statport)) & mask) == val) {
  281.       if ((INP & MASK_EXCEP) != NOT_EXCEP) return ct_test();
  282.       if (timer()-t0 > tout) {
  283.          ct_psw.flags |= CT_CHECKED;
  284.          return ct_error = (INP&MASK_READY)==NOT_READY ? Q2E_BUSY : Q2E_DEAD;
  285.       }
  286.       HALT_CPU;
  287.    }
  288.    return 0;
  289. }
  290.  
  291. static int ct_reset(void)
  292. {
  293.    register long t;
  294.  
  295.    outportb(ctlport, ct_set.do_reset);
  296.    suspend(wait25ms);
  297.    outportb(DMACL != UNUSED ? DMACL : ctlport, ON);
  298.    t = timer();
  299.    while ((((INP=inportb(statport)) & MASK_RESET) != VAL_RESET)) {
  300.       if (timer()-t > MINTIME) goto error; HALT_CPU;
  301.    }
  302.    while (!(ct_test() & Q2E_POR)) {
  303.       if (timer()-t > MAXTIME) goto error; HALT_CPU;
  304.    }
  305.    while (ct_test() & Q2E_POR) {
  306.       if (timer()-t > MAXTIME) goto error; HALT_CPU;
  307.    }
  308.    while ((INP=inportb(statport) & MASK_STATE) == INV_STATE) {
  309.       if (timer()-t > MAXTIME) goto error; HALT_CPU;
  310.    }
  311.    return 0;
  312. error:
  313.    return -1;
  314. }
  315.  
  316. int ct_errbit(register unsigned m)
  317. {
  318.    register n = 0;
  319.  
  320.    if (m) {
  321.       if      (m & Q2E_DEAD) m &= Q2E_DEAD;
  322.       else if (m & Q2E_HARD) m &= Q2E_HARD;
  323.       for (n=16; n && !(m & 0x8000); --n, m<<=1);
  324.    }
  325.    return n;
  326. }
  327.  
  328. static void ct_end(void)
  329. {
  330.    if (!(ct_psw.flags & CT_OPENED)) {
  331.       errno = EFAULT;
  332.    } else {
  333.       if (ct_pic.base != UNUSED) {
  334.          setvect(ct_pic.number, ct_pic.old);
  335.          if (ct_pic.save & (1 << (ct_pic.ack & 7)))
  336.             outportb(ct_pic.base+1, ct_pic.save);
  337.       }
  338.       ct_psw.flags = 0;
  339.    }
  340. }
  341.  
  342. static void ct_pause(void)
  343. {
  344.    register long t; for (t=timer(); timer()-t <= MINTIME;) HALT_CPU;
  345. }
  346.  
  347. static int ct_begin(register struct init_data *d, int board_type)
  348. {
  349.    register WORD i;
  350.    static BYTE page_tab[] = {0x87,0x83,0x81,0x82,0x8f,0x8b,0x89,0x8A};
  351.    static BYTE addr_tab[] = { 0,   2,   4,   6,  0xC0,0xC4,0xC8,0xCC};
  352.    static BYTE cntr_tab[] = { 1,   3,   5,   7,  0xC2,0xC6,0xCA,0xCE};
  353.    register struct _ct_define *c;
  354.    register j; register long t;
  355.  
  356.    if ((i = board_type & MASK_BOARD) >= dim(ct_list)) {
  357.       errno = ENODEV; return CTE_FAULT;
  358.    } else {
  359.       c = ct_list[i];
  360.    }
  361.    i = d->base_address;
  362.    if (i & ~(c->valid_base)) {
  363.       errno = EINVDAT; return CTE_FAULT;
  364.    } else {
  365.       ct_set.control = i + c->off_control;
  366.       ct_set.data    = i + c->off_data;
  367.       DMAGO  = c->off_launch == UNUSED ? UNUSED : i + c->off_launch;
  368.       DMACL  = c->off_clear  == UNUSED ? UNUSED : i + c->off_clear;
  369.  
  370.       ct_set.mask_reset = c->mask_reset;
  371.       ct_set.val_reset  = c->val_reset;
  372.       ct_set.mask_event = c->mask_event;
  373.       ct_set.not_event  = c->not_event;
  374.       ct_set.mask_ready = c->mask_ready;
  375.       ct_set.not_ready  = c->not_ready;
  376.       ct_set.mask_excep = c->mask_excep;
  377.       ct_set.not_excep  = c->not_excep;
  378.       ct_set.mask_state = ct_set.mask_ready | ct_set.mask_excep;
  379.       ct_set.inv_state  = ct_set.not_ready  | ct_set.not_excep;
  380.       ct_set.mask_xfer  = c->mask_xfer;
  381.       ct_set.no_xfer    = c->no_xfer;
  382.       ct_set.mask_dma   = c->mask_dma;
  383.       ct_set.done_dma   = c->done_dma;
  384.  
  385.       ct_set.online   = c->set_online;
  386.       ct_set.request  = c->set_request | ct_set.online;
  387.       ct_set.do_reset = c->set_reset;
  388.    }
  389.    i = d->dma_number;
  390.    if (i == UNUSED) {
  391.       ct_dma.page = ct_dma.address = ct_dma.counter = UNUSED;
  392.       ct_dma.mask = ct_dma.mode    = ct_dma.clear   = UNUSED;
  393.       ct_set.dma_enable = 0;
  394.    } else if (i & ~7 || !((c->dma_valid >> i) & 1)) {
  395.       errno = EINVDAT; return CTE_FAULT;
  396.    } else {
  397.       ct_set.dma_enable = c->rundma[i];
  398.       ct_dma.page    = page_tab[i];
  399.       ct_dma.address = addr_tab[i];
  400.       ct_dma.counter = cntr_tab[i];
  401.       if (i & ~3) {/* slave device */
  402.          ct_dma.mask  = 0xd4;
  403.          ct_dma.mode  = 0xd6;
  404.          ct_dma.clear = 0xd8;
  405.       } else {/* primary device */
  406.          ct_dma.mask  = 0xA;
  407.          ct_dma.mode  = 0xB;
  408.          ct_dma.clear = 0xC;
  409.       }
  410.       i &= 3;
  411.       /* single mode, address increment, no auto-init */
  412.       ct_dma.write = 0x40 | DMA_WRDEV | i;
  413.       ct_dma.read  = 0x40 | DMA_RDDEV | i;
  414.    }
  415.    i = d->irq_number;
  416.    if (i == UNUSED) {
  417.       ct_pic.number = ct_pic.base = UNUSED;
  418.       ct_set.int_enable = ct_set.done_enable = 0;
  419.    } else if (i & ~15) {
  420.       errno = EINVDAT; return CTE_FAULT;
  421.    } else {
  422.       ct_set.int_enable  = c->ienable;
  423.       ct_set.done_enable = c->denable ? c->denable : c->ienable;
  424.  
  425.       if (i & ~7) {/* slave controller */
  426.          ct_pic.number = i + 0x68;
  427.          ct_pic.base   = 0xA0;
  428.       } else {/* primary controller */
  429.          ct_pic.number = i + 8;
  430.          ct_pic.base   = 0x20;
  431.       }
  432.       i &= 7;
  433.       ct_pic.old   = getvect(ct_pic.number);
  434.       ct_pic.ack   = 0x60 | i; /* specific EOI */
  435.       ct_pic.save  = inportb(ct_pic.base + 1);
  436.       ct_pic.chain = ct_pic.old && ~(ct_pic.save >> i) & 1;
  437.    }
  438.    wait03us = suspend_value(3);
  439.    wait25ms = suspend_value(25000);
  440.  
  441.    if ((board_type & SKIP_RESET) == 0) {
  442.       if (ct_reset()) return (errno = EFAULT, CTE_DEAD);
  443.    }
  444.    if (ct_pic.base != UNUSED) {
  445.       setvect(ct_pic.number, cthandle);
  446.       if ((i = 1 << (ct_pic.ack & 7)) & ct_pic.save)
  447.          outportb(ct_pic.base+1, ~i & ct_pic.save);
  448.    }
  449.    ct_error = 0; ct_psw.flags |= CT_OPENED;
  450.    for (t=timer(), j=0;;) {
  451.       i = ct_test();
  452.       if (i & Q2E_WRP) ct_psw.flags |= CT_PROTECT;
  453.       if (!(i & ~(Q2E_BOM|Q2E_FIL|Q2E_WRP))) return 0;
  454.       if (timer()-t > MAXTIME) break;
  455.       if (!(i & Q2E_POR) && ++j >= NTRY) break;
  456.       ct_pause();
  457.    }
  458.    ct_end(); errno = EFAULT; return ct_errbit(i);
  459. }
  460.  
  461. static int ct_issue(int c)
  462. {
  463.    register unsigned long tick;
  464.  
  465.    if (ct_wait(MASK_STATE,INV_STATE,timer(),MINTIME) & Q2E_STOP) goto end;
  466.  
  467.    ct_psw.flags &= ~CT_CHECKED;
  468.    outportb(cmdport, lastcmd=c);
  469.    outportb(ctlport, REQ);
  470.    if (ct_wait(MASK_READY,NOT_READY,timer(),MINTIME) & Q2E_HARD) goto end;
  471.    ct_psw.flags &= ~CT_EVENT;
  472.    INP = (INP & ~ct_set.mask_event) | ct_set.not_event;
  473.    outportb(ctlport, ON|EI); /* Clear request, interrupt enable */
  474.    WAIT_BUSY(tick);
  475.    return 0;
  476. error:
  477.    ct_error = Q2E_DEAD;
  478.    ct_psw.flags |= CT_CHECKED;
  479. end:
  480.    return ct_errbit(ct_error);
  481. }
  482.  
  483. static int ct_complete(void)
  484. {
  485.    register long t;
  486.    for (t=timer();;) {
  487.       if (((INP=inportb(statport)) & MASK_STATE)!=INV_STATE) break;
  488.       if (timer()-t > MAXTIME) return (ct_error = Q2E_DEAD, CTE_DEAD);
  489.       HALT_CPU;
  490.    }
  491.    return 0;
  492. }
  493.  
  494. static int ct_iodma(int c, void *buf, unsigned length)
  495. {
  496.    register unsigned k;
  497.    register unsigned inp;
  498.    register long t, t0;
  499.    long address;
  500.  
  501.    address = ptr2abs(buf);
  502.    if (DMA_MAIN & 0xf0) {
  503.       /* Secondary DMA requires word alignment */
  504.       if (address & 1 || length & 1) return (errno = EINVMEM, CTE_FAULT);
  505.       address >>= 1;
  506.       length  >>= 1;
  507.    }
  508.    length -= 1;
  509.    /* Check for writing across DMA page */
  510.    if (((address+length) ^ address) & ~0xffffL)
  511.       return (errno = EINVMEM, CTE_FAULT);
  512.  
  513.    t0 = timer();
  514.    if (lastcmd!=c) {
  515.       if (DMACL != UNUSED) outportb(DMACL, 0);
  516.       /********** Issue a command **********/
  517.       outportb(cmdport, lastcmd=c);
  518.       outportb(ctlport, REQ);
  519.       if (ct_wait(MASK_READY, NOT_READY,
  520.                  (c & Q2_READBIT ? timer() : t0),
  521.                  (c & Q2_READBIT ? MINTIME : MAXTIME)) & Q2E_HARD)
  522.          goto error;
  523.       outportb(ctlport, ON|ED|DMA);
  524.       WAIT_BUSY(t);
  525.    }
  526.    /* Clear status */
  527.    ct_psw.flags &= ~(CT_EVENT|CT_CHECKED);
  528.    INP = (INP & ~ct_set.mask_event) | ct_set.not_event;
  529.  
  530.    /********** Initialise DMA **********/
  531.    outportb(ct_dma.mask, 4|(ct_dma.read & 3));
  532.    outportb(ct_dma.mode, c & Q2_READBIT ? ct_dma.read : ct_dma.write);
  533.    outportb(ct_dma.page, (WORD)(address >> 16));
  534.  
  535.    if (DMA_MAIN & 0xf0) {/* secondary controller */
  536.       outport(ct_dma.address, (WORD)address);
  537.       outport(ct_dma.counter, length);
  538.    } else {
  539.       disable();
  540.       outportb(ct_dma.clear,   0);
  541.       outportb(ct_dma.address, (WORD)address);
  542.       outportb(ct_dma.address, (WORD)address>>8);
  543.       outportb(ct_dma.counter, length);
  544.       outportb(ct_dma.counter, length>>8);
  545.       enable();
  546.    }
  547.    if (c & Q2_READBIT) {
  548.       if (ct_wait(DIRC,XOFF,t0,MAXTIME) & Q2E_HARD) goto error;
  549.    }
  550.    if (DMAGO != UNUSED) outportb(DMAGO, 0);
  551.    outportb(ct_dma.mask, (ct_dma.read & 3));
  552.  
  553.    /* Wait for the end of operation */
  554.    for (;;) {
  555.       INP = inp = inportb(statport);
  556.       if ((INP & MASK_EXCEP) != NOT_EXCEP) {
  557.          if (ct_test() & Q2E_HARD) goto error;
  558.          break;
  559.       }
  560.       if (ct_set.mask_dma) {
  561.          if ((INP & ct_set.mask_dma) == ct_set.done_dma) break;
  562.       } else {
  563.          if ((INP & MASK_READY) != NOT_READY) break;
  564.       }
  565.       if (timer()-t0 > MAXTIME) goto error;
  566.       HALT_CPU;
  567.    }
  568.    /********** Get number of bytes transferred **********/
  569.    if (DMA_MAIN & 0xf0) {/* secondary controller */
  570.       k = inport(ct_dma.counter);
  571.       k = (length - k) << 1;
  572.    } else {
  573.       disable();
  574.       outportb(ct_dma.clear, 0);
  575.       k  = inportb(ct_dma.counter);
  576.       k |= inportb(ct_dma.counter) << 8;
  577.       enable();
  578.       k = length - k;
  579.    }
  580.    if (!(c & Q2_READBIT) &&
  581.       (inp & MASK_READY) == NOT_READY && (INP & MASK_READY) == NOT_READY) {
  582.       (void)ct_wait(MASK_READY,NOT_READY,t0,MAXTIME);
  583.    }
  584.    return k;
  585.  
  586.    /********** Error occured **********/
  587. error:
  588.    if (DMACL != UNUSED) outportb(DMACL, 0);
  589.    return (errno = EFAULT, CTE_FAULT);
  590. }
  591.  
  592. static int ct_inout(int c, void *buf, unsigned length)
  593. {
  594.    if (ct_wait(MASK_READY,NOT_READY,timer(),
  595.               (c & Q2_READBIT ? MAXTIME : WAITIME)) & Q2E_STOP)
  596.       return -1;
  597.    return DMA_MAIN == UNUSED ?
  598.              ct_iobyte(c, buf, length, MAXTIME) :
  599.              ct_iodma(c, buf, length);
  600. }
  601.  
  602. int streamer(register int op, void *ptr, int arg)
  603. {
  604.    register i;
  605.    register long t;
  606.  
  607.    op |= 'z'^'Z';
  608.    if (op == '?') {
  609.       for (op=dim(ct_list); --op >= 0;) {
  610.          for (i=ct_list[op]->naliases; --i >= 0;) {
  611.             if (strnicmp(ct_list[op]->aliases[i], ptr, ALIASLEN) == 0)
  612.                goto end;
  613.          }
  614.       }
  615.       goto end;
  616.    } else if (op == 'o') {/* open device */
  617.       op = ct_psw.flags & CT_OPENED ?
  618.          (errno=EFAULT, CTE_OPENED) :
  619.          ct_begin((struct init_data *)ptr, arg);
  620.       goto end;
  621.    }
  622.    if (!(ct_psw.flags & CT_OPENED)) return (errno=EFAULT, CTE_CLOSED);
  623.    switch (op) {
  624.       case 'c': /* end - close device */
  625.          ct_end();
  626.          op = 0;
  627.          break;
  628.       case 't': /* read status */
  629.          op = ct_errbit(ct_psw.flags&CT_CHECKED ? ct_error : ct_test());
  630.          if (ptr) {
  631.             ((struct qic02_word_status *)ptr)->status = ct_error;
  632.             ((struct qic02_word_status *)ptr)->error_cnt =
  633.                (statbuf[2] << 8) | statbuf[3];
  634.             ((struct qic02_word_status *)ptr)->underrun_cnt =
  635.                (statbuf[4] << 8) | statbuf[5];
  636.          }
  637.          ct_psw.flags &= ~CT_CHECKED;
  638.          break;
  639.       case 'n': /* rewind */
  640.      for (op=0, i=0;;) {
  641.             if (ct_issue(Q2_REWIND) == 0) {
  642.                for (t=timer(); timer()-t <= MAXTIME;) {
  643.                   if (((INP=inportb(statport))&MASK_STATE)!=INV_STATE) break;
  644.                   HALT_CPU;
  645.            }
  646.            ct_test();
  647.            if (ct_error & Q2E_HARD) break;
  648.            if (ct_error & Q2E_BOM) goto end;
  649.         }
  650.         if (++i >= NTRY) break;
  651.         if (ct_reset()) {
  652.                ct_error = Q2E_DEAD; break;
  653.         }
  654.      }
  655.      op = ct_error & ~Q2E_WRP;
  656.      op = op ? ct_errbit(op) : CTE_FAULT;
  657.          break;
  658.       case 'i': /* issue a command */
  659.          arg &= 255;
  660.          if (arg == Q2_RDDATA || arg == Q2_WRDATA || arg == Q2_RDSTAT) {
  661.             errno = EINVAL; op = CTE_FAULT;
  662.          } else {
  663.             ct_psw.flags &= ~CT_CHECKED;
  664.             if ((op = ct_issue(arg)) == 0) op = ct_complete();
  665.          }
  666.          break;
  667. #if 0
  668.       case 'f': /* forward space file(s) */
  669.          for (op=0; op<arg; op++) {
  670.             ct_issue(Q2_RDMARK);
  671.             if (ct_complete() != 0) break;
  672.             blkdone += 1;
  673.          }
  674.          if (op != arg) ct_test();
  675.          break;
  676. #endif
  677.       case 'r': /* read */
  678.          if ((op = ct_inout(Q2_RDDATA, ptr, arg)) != arg) {
  679.             if (!(ct_psw.flags & CT_CHECKED)) ct_test();
  680.             if (ct_error & Q2E_FIL && !(ct_error & Q2E_HARD)) {
  681.                /* file mark detected */ op = 0;
  682.             }
  683.          }
  684.          break;
  685.       case 'w': /* write */
  686.          if (ct_psw.flags & CT_PROTECT) {
  687.             ct_psw.flags |= CT_CHECKED;
  688.             ct_error = Q2E_WRP;
  689.             op = CTE_FAULT;
  690.             break;
  691.          }
  692.          if (!arg) {
  693.             /* write file mark */
  694.             if (ct_issue(Q2_WRMARK)!=0 || ct_complete()!=0) {
  695.                ct_test();
  696.                op = -1;
  697.             }
  698.          } else {
  699.             op = ct_inout(Q2_WRDATA, ptr, arg);
  700.          }
  701.          break;
  702.       default:
  703.          errno = EINVFNC;
  704.          op = CTE_FAULT;
  705.    }
  706. end:
  707.    return op;
  708. }
  709. #endif
  710.